//////////////////////////////////////////////////////////////////////////
#pragma once


//////////////////////////////////////////////////////////////////////////
#include "Math/Math.hpp"


namespace Math
{
	class Point3f;

	class Vector3f
	{
	public:
		// Element index's.
		static const size_t						kXIndex		=	0;
		static const size_t						kYIndex		=	1;
		static const size_t						kZIndex		=	2;

		// Pull the type from the base Simd definition.
		typedef Vector3f						ValueType_t;
		typedef const Vector3f&					ParamType_t;

		// Construction.
		Vector3f();
		Vector3f( const Vector3f& rhs );
		Vector3f( const Point3f& rhs );
		Vector3f( float x, float y, float z );


		// Accessors.
		float						X() const;
		float						Y() const;
		float						Z() const;
		void						X( float x );
		void						Y( float y );
		void						Z( float z );

		// Array accessors.
		float						operator ()( size_t idx ) const;
		void						operator ()( size_t idx, float v );

		//
		bool						operator ==( const Vector3f& rhs ) const;
		bool						operator !=( const Vector3f& rhs ) const;

		// Assignments.
		void						Set( float x, float y, float z );
		const Vector3f&				operator =( const Vector3f& rhs );

		// Operator overloads.
		Vector3f					operator -() const;
		Vector3f					operator -( const Vector3f& rhs ) const;
		Vector3f					operator +( const Vector3f& rhs ) const;
		float						operator *( const Vector3f& rhs ) const;
		Vector3f					operator *( float rhs ) const;
		Vector3f					operator /( float rhs ) const;
		void						operator -=( const Vector3f& rhs );
		void						operator +=( const Vector3f& rhs );
		void						operator *=( float rhs );
		void						operator /=( float rhs );

		// Member functions.
		void						Normalize();
		void						Cross( const Vector3f& rhs );
		bool						IsValid() const;

		// Static initializers.
		static const Vector3f		Zero();
		static const Vector3f		XAxis();
		static const Vector3f		YAxis();
		static const Vector3f		ZAxis();

	private:
		// Implementation data.
		float						mX;
		float						mY;
		float						mZ;
	};


	//////////////////////////////////////////////////////////////////////////
	// Helper operator.
	inline Vector3f					operator *( float lhs, const Vector3f& rhs );


	//////////////////////////////////////////////////////////////////////////
	// Helper functions.
	inline float					Dot( const Vector3f& lhs, const Vector3f& rhs );
	inline Vector3f					Normalize( const Vector3f& rhs );
	inline Vector3f					Cross( const Vector3f& lhs, const Vector3f& rhs );
	inline float					Magnitude( const Vector3f& lhs );
	inline float					MagnitudeSquared( const Vector3f& lhs );
	inline Vector3f					Multiply( const Vector3f& lhs, const Vector3f& rhs );
	inline Vector3f					Reflect( const Vector3f& v, const Vector3f& axis );
	inline Vector3f					Refract( const Vector3f& i, const Vector3f& n, float eta );
}


// Include the implementations.
#include "Detail/Vector3f_Impl.hpp"
